/*!
 * @file pawirr.cpp
 * @brief Ciało pawirr.hh
 */

#include "engine/pawirr.hh"
using namespace std;

/*--------------------------------------------------------------------------*/

moduleKeyboard *pawirr::keyboard = NULL;
moduleGraphic *pawirr::graphic = NULL;
moduleSet *pawirr::set = NULL;
moduleTemplate *pawirr::temp = NULL;
moduleModes *pawirr::m = NULL;

std::list<moduleBase*> *pawirr::listModule = NULL;
std::list<modeBase*> *pawirr::listMode = NULL;

inifile *pawirr::config = NULL;

bool pawirr::isLoop = false;

unsigned long int pawirr::currentTime = 0;
unsigned long int pawirr::FPSCount = 0;

/*--------------------------------------------------------------------------*/

pawirr::pawirr(){
}

/*--------------------------------------------------------------------------*/

void pawirr::init(){

	pawirr::config = new inifile(PATH_CONFIG);

	pawirr::boot();
}

/*--------------------------------------------------------------------------*/

void pawirr::boot() {

	log::info(LANG_LOG_START);

	pawirr::listModule = new std::list<moduleBase*>;
	pawirr::listMode = new std::list<modeBase*>;

	pawirr::init_sdl();

	pawirr::sys_loadModule(&pawirr::set);
	pawirr::sys_loadModule(&pawirr::keyboard);
	pawirr::sys_loadModule(&pawirr::graphic);
	pawirr::sys_loadModule(&pawirr::temp);
	pawirr::sys_loadModule(&pawirr::m);

	pawirr::sys_loadMode(&pawirr::m->console);
	pawirr::sys_loadMode(&pawirr::m->world);

	pawirr::isLoop = true;
}

/*--------------------------------------------------------------------------*/

void pawirr::init_sdl() {

	if (SDL_Init(SDL_INIT_EVERYTHING) < 0) {

		stringstream ss;
		ss << LANG_SDL_MAIN_PREFIX << SDL_GetError() << endl;

		log::crash(ss.str());

	}

	atexit(SDL_Quit);

	stringstream ss;
	ss << LANG_SDL_MAIN_PREFIX << LANG_GLOBAL_OK;
	log::info(ss.str());
}

/*--------------------------------------------------------------------------*/

void pawirr::loop() {

	pawirr::m->world->loadMap( string(PATH_DIR_MAPS) + string("new/") );

	log::info(LANG_LOOP_START);

	/*
	 * Startowanie wątku obliczeniowego, funkcji dla głównego wątku
	 */
	pawirr::mainLoop();

	log::info(LANG_LOOP_STOP);

	/*
	 * Kończenie programu
	 */
	pawirr::quit(QNORMAL);
}

/*--------------------------------------------------------------------------*/

void pawirr::quit(_quit_type et) {

	switch (et) {

	case QNORMAL:

		if (pawirr::isLoop) {
			pawirr::isLoop = false;
			//dokończenie pełnego okrążenia pętli głównej
		} else {
			log::info(LANG_QUIT_NORMAL);
			//zwalnianie pamięci etc.
			//pawirr::logStream.close();
		}

		break;

	case QBRUTAL:

		log::info(LANG_QUIT_BRUTAL);
		cout << "QUIT_BRUTAL" << endl;

		exit(666);
		break;
	}

}

/*--------------------------------------------------------------------------*/

int pawirr::mainLoop() {

	pawirr::currentTime = SDL_GetTicks();
	unsigned long int lastTime = pawirr::getTime();
	float deltaT = 0;

	while (pawirr::isLoop) {

		pawirr::currentTime = SDL_GetTicks();

		pawirr::keyboard->checkInput();

		/*
		 * Włączanie/wyłączanie konsoli
		 */
		if (pawirr::keyboard->isPressed(k_console)) {
			if (pawirr::m->console->setActive == MA_ON)
				pawirr::m->console->setActive = MA_OFF;
			else
				pawirr::m->console->setActive = MA_ON;
		}

		/*
		 * Wywoływanie obsługi wejścia od najgłębszych warstw do frontu
		 * dla aktywnych trybów.
		 */
		for (int i = MK_IMPORTANT; i <= MK_NOTIMPORTANT; i++) {

			for (list<modeBase*>::iterator Iter = pawirr::listMode->begin(); Iter
					!= pawirr::listMode->end(); ++Iter) {

				if (i == (*Iter)->setActive && ((*Iter)->setActive == MA_ON
						|| (*Iter)->setActive == MA_ALWAYS)) {
					(*Iter)->input();
				}
			}
		}



		/*--------------------------------------------------------------------
		 * Obliczenie przesunięcia dla cząstek i ich malowanie
		 */
		pawirr::graphic->_pcs->calculate();

		/*
		 * Wywyoływanie obliczeniówki. Tutaj kolejność jest nieistotna
		 */
		for (list<modeBase*>::iterator Iter = pawirr::listMode->begin(); Iter
				!= pawirr::listMode->end(); ++Iter) {

			if ((*Iter)->setActive == MA_ON || (*Iter)->setActive == MA_ALWAYS) {
				(*Iter)->calculate();
			}
		}

		/*
		 * Wywoływanie renderowania od najgłębszych warstw do frontu
		 * dla aktywnych trybów.
		 */
		pawirr::graphic->setRenderMode(RM_3D);
		for (int i = MD_BACKGROUND; i <= MD_FOREGROUND; i++) {

			for (list<modeBase*>::iterator Iter = pawirr::listMode->begin(); Iter
					!= pawirr::listMode->end(); ++Iter) {

				if (i == (*Iter)->setActive && ((*Iter)->setActive == MA_ON
						|| (*Iter)->setActive == MA_ALWAYS)) {
					(*Iter)->render3d();
				}
			}

			++pawirr::FPSCount;
		}


		if(pawirr::FPSCount > 5){

			deltaT = pawirr::getTime() - lastTime;
			lastTime = pawirr::getTime();

			pawirr::m->world->_area->obj->physic(deltaT);
		}

		/*--------------------------------------------------------------------
		 * Obliczenie przesunięcia dla cząstek i ich malowanie
		 */
		pawirr::graphic->_pcs->draw();

		/*--------------------------------------------------------------------
		 * Wyświetlanie elementów 3d pochodzących z gfxDebug
		 */
		pawirr::graphic->_dbg->render3d();

		/*--------------------------------------------------------------------
		 * Odpalanie postefektów. Dotyczą one tylko sceny 3D.
		 * Wersja 2D jest malowana tradycyjnie
		 */
		pawirr::graphic->_fx->paintAll();

		/*
		 * Wywoływanie renderowania od najgłębszych warstw do frontu
		 * dla aktywnych trybów.
		 */
		pawirr::graphic->setRenderMode(RM_2D);
		for (int i = MD_BACKGROUND; i <= MD_FOREGROUND; i++) {

			for (list<modeBase*>::iterator Iter = pawirr::listMode->begin(); Iter
					!= pawirr::listMode->end(); ++Iter) {

				if (i == (*Iter)->setActive && ((*Iter)->setActive == MA_ON
						|| (*Iter)->setActive == MA_ALWAYS)) {
					(*Iter)->render2d();
				}
			}

		}

		/*--------------------------------------------------------------------
		 * Wyświetlanie elementów 2d pochodzących z gfxDebug
		 */
		pawirr::graphic->_dbg->render2d();

		pawirr::graphic->flipFrame();
	}

	return 0;
}

/*--------------------------------------------------------------------------*/

unsigned long int pawirr::getFPSCount(){
	return pawirr::FPSCount;
}

/*--------------------------------------------------------------------------*/

unsigned long int pawirr::getTime() {
	return pawirr::currentTime;
}

/*--------------------------------------------------------------------------*/

moduleBase *pawirr::getModuleByName(std::string name) {

	for (list<moduleBase*>::iterator Iter = pawirr::listModule->begin(); Iter
			!= pawirr::listModule->end(); ++Iter) {

		if ((*Iter)->getName() == name) {
			return (*Iter);
		}
	}

	return NULL;

}

/*--------------------------------------------------------------------------*/

modeBase *pawirr::getModeByName(std::string name) {

	for (list<modeBase*>::iterator Iter = pawirr::listMode->begin(); Iter
			!= pawirr::listMode->end(); ++Iter) {

		if ((*Iter)->getName() == name) {
			return (*Iter);
		}
	}

	return NULL;

}

/*--------------------------------------------------------------------------*/
